﻿using System.IO;

namespace Ultima.Xna.Data
{
    public class FileIndex
    {
        private IndexEntry3D[] _indices;
        private Stream _stream;

        public IndexEntry3D[] Indices { get { return _indices; } }
        public Stream Stream { get { return _stream; } }

        public Stream Seek(int index)
        {
            int length, extra;
            bool patched;

            return Seek(index, out length, out extra, out patched);
        }

        public Stream Seek(int index, out int length, out int extra, out bool patched)
        {
            if (index < 0 || index >= _indices.Length)
            {
                length = extra = 0;
                patched = false;
                return null;
            }

            IndexEntry3D e = _indices[index];

            if (e.Lookup < 0)
            {
                length = extra = 0;
                patched = false;
                return null;
            }

            length = e.Length & 0x7FFFFFFF;
            extra = e.Extra;

            if ((e.Length & (1 << 31)) != 0)
            {
                patched = true;

                Verdata.Stream.Seek(e.Lookup, SeekOrigin.Begin);
                return Verdata.Stream;
            }
            else if (_stream == null)
            {
                length = extra = 0;
                patched = false;
                return null;
            }

            patched = false;

            _stream.Seek(e.Lookup, SeekOrigin.Begin);
            return _stream;
        }

        public FileIndex(string idxFile, string mulFile, int length, int file)
        {
            _indices = new IndexEntry3D[length];

            string idxPath = FileManager.GetFilePath(idxFile);
            string mulPath = FileManager.GetFilePath(mulFile);

            if (idxPath != null && mulPath != null)
            {
                using (FileStream index = new FileStream(idxPath, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    BinaryReader bin = new BinaryReader(index);
                    _stream = new FileStream(mulPath, FileMode.Open, FileAccess.Read, FileShare.Read);

                    int count = (int)(index.Length / 12);

                    for (int i = 0; i < count && i < length; ++i)
                    {
                        _indices[i].Lookup = bin.ReadInt32();
                        _indices[i].Length = bin.ReadInt32();
                        _indices[i].Extra = bin.ReadInt32();
                    }

                    for (int i = count; i < length; ++i)
                    {
                        _indices[i].Lookup = -1;
                        _indices[i].Length = -1;
                        _indices[i].Extra = -1;
                    }
                }
            }

            IndexEntry5D[] patches = Verdata.Patches;

            for (int i = 0; i < patches.Length; ++i)
            {
                IndexEntry5D patch = patches[i];

                if (patch.File == file && patch.Index >= 0 && patch.Index < length)
                {
                    _indices[patch.Index].Lookup = patch.Lookup;
                    _indices[patch.Index].Length = patch.Length | (1 << 31);
                    _indices[patch.Index].Extra = patch.Extra;
                }
            }
        }
    }
}